#ifndef __M_ROUTE_H__
#define __M_ROUTE_H__
#include "../mqcommon/mq_logger.hpp"
#include "../mqcommon/mq_helper.hpp"
#include "../mqcommon/mq_msg.pb.h"

namespace mymq
{
    class Router
    {
    public:
        static bool RoutingKeyIsLegal(const std::string& routing_key)
        {
            // a~z A~Z 0~9 . _
            for (auto& ch : routing_key)
            {
                if ((ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') ||
                    (ch == '.' || ch == '_'))
                {
                    continue;
                }
                return false;
            }
            return true;
        }

        static bool BindingKeyIsLegal(const std::string& binding_key)
        {
            // a~z A~Z . _ * #
            for (auto& ch : binding_key)
            {
                if ((ch >= 'a' && ch <= 'z') ||
                    (ch >= 'A' && ch <= 'Z') ||
                    (ch >= '0' && ch <= '9') ||
                    (ch == '.' || ch == '_') ||
                    (ch == '*' || ch == '#'))
                {
                    continue;
                }
                return false;
            }

            // * # 都必须独立存在  news.*.music.#
            std::vector<std::string> sub_words;
            StrHelper::split(binding_key, ".", sub_words);
            for (auto& word : sub_words)
            {
                if (word.size() > 1 && (word.find('*') != std::string::npos || 
                    word.find('#') != std::string::npos))
                    return false;
            }

            // # 的两边不可以存在 # 或 *
            for (int i = 1; i < sub_words.size(); i++)
            {
                // # 左边存在 # 或者 *
                if (sub_words[i] == "#" && (sub_words[i-1] == "#" || sub_words[i-1] == "*"))
                    return false;
                // # 右边存在 *
                if (sub_words[i] == "*" && sub_words[i-1] == "#")
                    return false;
            }

            return true;
        }
        static bool Route(ExchangeType type, const std::string& routing_key, const std::string& binding_key)
        {
            if (type == ExchangeType::DIRECT)
                return routing_key == binding_key;
            else if (type == ExchangeType::FANOUT)
                return true;

            // 主题匹配模式
            // 1.获得 bindingkey 和 routingkey 的单词
            std::vector<std::string> b_keys, r_keys;
            int n_bkey = StrHelper::split(binding_key, ".", b_keys);
            int n_rkey = StrHelper::split(routing_key, ".", r_keys);

            // 2.创建 dp 表，为了方便填表，多开一行一列，填表时注意下标的映射
            std::vector<std::vector<bool>> dp(n_bkey + 1, std::vector<bool>(n_rkey + 1, false));
            dp[0][0] = true;
            // 如果binding_key 以 # 开头，将本行的第 0 列设置为 true
            if (b_keys[0] == "#")
                dp[1][0] = true;

            // 填表
            for (int i = 1; i <= n_bkey; i++)
            {
                for (int j = 1; j <= n_rkey; j++)
                {
                    // 两个单词匹配 或者 存在*
                    if (b_keys[i - 1] == r_keys[j - 1] || b_keys[i - 1] == "*")
                        dp[i][j] = dp[i - 1][j - 1];
                    else if (b_keys[i - 1] == "#")
                        dp[i][j] = dp[i - 1][j - 1] | dp[i - 1][j] | dp[i][j - 1];
                }
            }
            return dp[n_bkey][n_rkey];
        }

    };
}

#endif